package mediadisplay.viewerarea 
{
	import com.greensock.TweenLite;
	import com.theflashblog.util3d.SimpleZSorter;
	import flash.display.GradientType;
	import flash.display.SpreadMethod;
	import flash.display.Sprite;
	import flash.display.StageDisplayState;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	import mediadisplay.timeline.controls.ControlButton;
	import mediadisplay.ui.TextArea;
	/**
	 * ...
	 * @author Anders Figenschow
	 */
	public class ViewerArea extends Sprite
	{
		public var objectsOnScreen:Array;
		public var current:int;
		public var objectsContainer:Sprite;
		private var obMask:Sprite;
		private var _width:Number;
		private var _height:Number;
		private var tweenTime:Number;
		private var lastFocusedElement:ScreenText;
		private var startMouseDownX:Number;
		private var startMouseDownY:Number;
		private var ctrlKeyIsDown:Boolean = false;
		private var startMouseDownZ:Number;
		private var previousX:Number;
		private var previousY:Number;
		public var _main:Main;
		public var mouseIsDown:Boolean;
		private var coords:Coordinates;
		public var centerClip:Sprite;
		private var aDown:Boolean = false;
		private var screenElementTargeted:Boolean;
		private var targetedElement:ScreenText;
		public var backgroundImage:Background;
		private var activeElement:ScreenText;
		public var currentMaskSize:Number = 300;
		
		public function ViewerArea(main:Main) 
		{
			_main = main;
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			var fType:String = GradientType.LINEAR;
			var colors:Array = [ 0x333333, 0 ];
			var alphas:Array = [ 1, 1 ];
			var ratios:Array = [ 0, 255 ];
			var matr:Matrix = new Matrix();
			matr.createGradientBox( 330, 1024, 0, 0, 0 );
			matr.rotate(Math.PI/2);
			var sprMethod:String = SpreadMethod.PAD;
			
			setTweenTime(0.3);
			
			resize();
			drawBorder();
			makeBackgroundImageArea();
			
			graphics.beginFill(0);
			graphics.drawRect(0, 0, 1024, 330);
			graphics.endFill();
			//graphics.beginGradientFill( fType, colors, alphas, ratios, matr, sprMethod );
			//graphics.drawRect(0, 0, 1024, 330);
			//graphics.endFill();
			
			obMask = new Sprite();
			addChild(obMask);
			drawMask(300);
			
			coords = new Coordinates();
			addChild(coords);
			coords.x = 400;
			coords.y = 20;
			
			addEventListener(Event.ENTER_FRAME, enterframe);
			addEventListener(Event.REMOVED_FROM_STAGE, cleanup);
			addEventListener(Event.RESIZE, resize);
			addEventListener(MouseEvent.MOUSE_DOWN, stageMouseDownHandler);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
			stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
			
			var fullscreen:ControlButton = new ControlButton(" ", "makes fullscreen!");
			addChild(fullscreen);
			fullscreen.y = 0;
			fullscreen.addEventListener(MouseEvent.CLICK, toggleFullscreen);
			
			reset();
			//objectsContainer.scaleX = objectsContainer.scaleY = 0.5;
			
		}
		
		private function toggleFullscreen(e:MouseEvent):void 
		{
			var rect:Rectangle = new Rectangle(0, 0, 1024, 576);
			var i:int;
			var element:ScreenText;
			
			if (stage.displayState == StageDisplayState.NORMAL) {
				stage.fullScreenSourceRect = rect;
				stage.displayState = StageDisplayState.FULL_SCREEN;
				_main.soundgraph.visible = false;
				for (i = 0; i < objectsOnScreen.length; i++) 
				{
					element = objectsOnScreen[i];
					element.editToggle(false);
				}
				_main.menu.visible = false;
				coords.visible = false;
				drawMask(576);
				currentMaskSize = 576;
			} else {
				for (i = 0; i < objectsOnScreen.length; i++) 
				{
					element = objectsOnScreen[i];
					element.editToggle(true);
				}
				_main.soundgraph.visible = true;
				_main.menu.visible = true;
				coords.visible = true;
				currentMaskSize = 300;
				drawMask(300);
				stage.fullScreenSourceRect = null;
				stage.displayState = StageDisplayState.NORMAL;
			}
			setMask();
		}
		
		public function setMode():void {
			var rect:Rectangle = new Rectangle(0, 0, 1024, 576);
			var i:int;
			var element:ScreenText;
			
			if (Main.VIEW_MODE == "justView") {
				_main.soundgraph.visible = false;
				for (i = 0; i < objectsOnScreen.length; i++) 
				{
					element = objectsOnScreen[i];
					element.editToggle(false);
				}
				_main.menu.visible = false;
				coords.visible = false;
				drawMask(576);
				currentMaskSize = 576;
				_main.removeLoginState();

			} 
			
			setMask();			
		}
		
		private function makeBackgroundImageArea():void 
		{
			backgroundImage = new Background(this);
			addChild(backgroundImage);
			backgroundImage.setBackgroundImage("bg.jpg");
		}
		
		private function enterframe(e:Event):void 
		{
			// update coordinate help text
			coords.change(objectsContainer.x, objectsContainer.y);
			SimpleZSorter.sortClips(objectsContainer);
		}
		private function keyDownHandler(e:KeyboardEvent):void 
		{
			if (e.ctrlKey) {
				ScreenText.HEY_IM_WORKING_HERE = true;
				ctrlKeyIsDown = true;
			}
		}
		
		private function keyUpHandler(e:KeyboardEvent):void 
		{
			ctrlKeyIsDown = false;
			if (mouseIsDown) return;
			ScreenText.HEY_IM_WORKING_HERE = false;
		}
		
		private function stageMouseDownHandler(e:MouseEvent):void 
		{
			if (e.currentTarget is ScreenText) {
				return;
			}
			mouseIsDown = true;
			startMouseDownX = -objectsContainer.x + mouseX;
			startMouseDownY = -objectsContainer.y + mouseY;
			startMouseDownZ = stage.mouseY;
			previousY = 0;
			
			stage.addEventListener(MouseEvent.MOUSE_MOVE, moveBackGroundHandler);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
		}
		
		private function moveBackGroundHandler(e:MouseEvent):void 
		{
			if (ScreenText.HEY_IM_WORKING_HERE) return;
			
			if (ctrlKeyIsDown) {
				var distanceZ:Number = (stage.mouseY - startMouseDownY);
				if (previousY > mouseY) {
					objectsContainer.z += distanceZ;
				} else {
					objectsContainer.z -= distanceZ;
				}
			} else {
				var distanceX:Number = (stage.mouseX - startMouseDownX) - objectsContainer.x;
				var distanceY:Number = (stage.mouseY - startMouseDownY) - objectsContainer.y;
				objectsContainer.x += distanceX / 2;
				objectsContainer.y += distanceY / 2;				
			}
			previousY = mouseY;
			
		}
		
		private function mouseUpHandler(e:MouseEvent):void 
		{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, moveBackGroundHandler);
			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			mouseIsDown = false;
		}
		
		public function setTweenTime(time:Number):void {
			tweenTime = time;
		}
		private function resize(e:Event = null):void 
		{
			_height = stage.stageHeight - 300;
			_width = 1024 * scaleY;
			
			drawBorder();
		}
		
		private function drawBorder():void 
		{
			graphics.clear();
			graphics.lineStyle(1, 0xff0000, 1, true);
			graphics.drawRect(0, 0, _width, _height);			
		}
		
		
		
		public function cleanup(e:Event = null):void 
		{
			removeEventListener(Event.REMOVED_FROM_STAGE, cleanup);
			for (var i:int = 0; i < objectsOnScreen.length; i++) 
			{
				var item:ScreenText = objectsOnScreen[i];
				objectsContainer.removeChild(item);
			}
			//removeEventListener(Event.ENTER_FRAME, enterframe);
			//removeEventListener(MouseEvent.MOUSE_DOWN, stageMouseDownHandler);
			//stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
			//stage.removeEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
			reset();
		}
		
		public function drawMask(height:Number = 600):void 
		{
			obMask.graphics.clear();
			obMask.graphics.beginFill(0xff0000);
			obMask.graphics.drawRect(0, 0, 1024, height);
			obMask.graphics.endFill();
			
		}
		public function setMask():void {
			mask = obMask;
		}
		public function reset():void {
			objectsOnScreen = new Array;
			
			if (objectsContainer) {
				centerClip.removeChild(objectsContainer);
				removeChild(centerClip);
			}
			centerClip = new Sprite;
			addChild(centerClip);
			objectsContainer = new Sprite;
			centerClip.addChild(objectsContainer);
			objectsContainer.x = -512;
			objectsContainer.y = -200;
			centerClip.x = 512;
			centerClip.y = 200;
			
			current = 0;
			
			setMask();
			
		}
		public function removeScreenElement(index:int):void {
			if (objectsOnScreen.length > 0) {
				objectsContainer.removeChild(objectsOnScreen[index]);
				objectsOnScreen.splice(index, 1);
			}
			
		}
		public function addScreenElement(txt:String, index:int, rule:Rule = null, randomPosition:Boolean = false, xpos:Number = 0, ypos:Number = 0, zpos:Number = 0, rotX:Number = 0, rotY:Number = 0, rotZ:Number = 0, scale:Number = 1, background:String = "", color:uint = 0xffffff, ignore:Boolean = false, interactionTarget:Number = -1):void {
			
			var rule:Rule = new Rule();
			
			// where should the element start on screen (should be modified with tools)
			rule.setStart(512, 150, 0, 1, 0xffffff, 1);
			// where should the element move on focus?  (should be modified with tools - if not, will be same as start values.)
			//rule.setTarget(512, 150, 0, 1, 0xffffff, 1);
			
			rule.setRule(0, 24, 250, 1, 0xffffff, -0.20);
			//if (randomPosition) rule.setRandomPosition();
			var imageURL:String = "";
			//if (objectsOnScreen.length == 3) imageURL = "expology.jpg";
			var element:ScreenText = new ScreenText(this, index, txt, rule, xpos, ypos, zpos, rotX, rotY, rotZ, scale, imageURL, background, color, ignore, interactionTarget);
			objectsContainer.addChild(element);
			//trace("element made with x=" + xpos + " y=" + ypos + " z=" + zpos + " rot=" + rot);
			element.visible = false;
			element.editToggle(true);
			objectsOnScreen.push(element);
			
			//placeAllElementesOnRandomPositions();
			//placeAllElementsOnYRow();
			placeAllElementsOnCustomMadePositions();
		}
		
		private function placeAllElementsOnCustomMadePositions():void 
		{
			for (var i:int = 0; i < objectsOnScreen.length; i++) {
				var element:ScreenText = objectsOnScreen[i];
				
				//element.x = element._xpos;
				//element.y = element._ypos;
				//element.z = element._zpos;
				//element.rotation = element._rot;
				
				//element.x = 212;
				//element.y = i * 20;
				//element.z = -i * 150;
				//
				//element.rotationY = -10 + Math.random() * 20;
				element.visible = true;
				if (!element.keepFullAlpha) element.alpha = 0.3;
			}			
		}
		
		public function moveElements(currentIndex:int):void {
			trace("moving element " + currentIndex);
			var currentElement:ScreenText = objectsOnScreen[currentIndex];
			currentElement.visible = true;
			currentElement.onScreen = true;
			//TweenLite.to(currentElement, 1, { x:currentElement._rule._targetX, y:currentElement._rule._targetY, z:currentElement._rule._targetZ, alpha:currentElement._rule._targetAlpha, scaleX:1.2, scaleY:1.2 } );
			TweenLite.to(currentElement, 1, { x:currentElement._rule._targetX, y:currentElement._rule._targetY, z:currentElement._rule._targetZ, alpha:currentElement._rule._targetAlpha, scaleX:currentElement._rule._targetScale, scaleY:currentElement._rule._targetScale } );
			
			//for (var i:int = 0; i < objectsOnScreen.length; i++) 
			//{
				//var element:ScreenText = objectsOnScreen[i];
				//if (element.onScreen && i != currentIndex) {
					//var newX:Number = element.x + element._rule._modX;
					//var newY:Number = element.y + element._rule._modY;
					//var newZ:Number = element.z + element._rule._modZ;
					//var newAlpha:Number = Math.max(0, element.alpha + element._rule._modAlpha);
					//TweenLite.to(element, 1, { x:newX, y:newY, z:newZ, alpha:newAlpha, scaleX:1, scaleY:1 });					
				//}
			//}
		}
		
		private function placeAllElementsOnYRow():void 
		{
			for (var i:int = 0; i < objectsOnScreen.length; i++) {
				var element:ScreenText = objectsOnScreen[i];
				element.x = 212;
				//element.y = 500 + (element._rule._modY * i);
				element.y = i * 10;
				//element.z = -i * 50;
				element.rotationY = -10 + Math.random() * 20;
				//element.rotationZ = -10 + Math.random() * 20;
				element.visible = true;
				element.alpha = 1;
			}
			
		}
		
		public function placeAllElementesOnRandomPositions():void {
			for (var i:int = 0; i < objectsOnScreen.length; i++) {
				var element:ScreenText = objectsOnScreen[i];
				element.x = Math.random() * 2000;
				element.y = Math.random() * 2000;
				element.z = Math.random() * 10000;
				element.rotationY = -10 + Math.random() * 20;
				//element.rotationZ = -10 + Math.random() * 20;
				element.visible = true;
				element.alpha = 1;
			}
		}
		
		public function moveCameraToPosition(xPos:Number, yPos:Number, zPos:Number, rotationX:Number = 0, rotationY:Number = 0, rotationZ:Number = 0):void {
			TweenLite.to(objectsContainer, tweenTime, { x: -xPos, y: -yPos, z: -zPos } );	
		}
		
		public function moveCamera(currentIndex:int):void {
			var element:ScreenText = objectsOnScreen[currentIndex];
			
			if (element._ignore) return;
			//if (element.tf.text.indexOf(".png") > -1 || element.tf.text.indexOf(".jpg") > -1) return;
			
			if (lastFocusedElement != null && !lastFocusedElement.keepFullAlpha) {
				lastFocusedElement.alpha = 0.3;
			}
			
			lastFocusedElement = element;
			var newX:Number = element.x;
			var newY:Number = element.y;
			var newZ:Number = element.z;
			var newAlpha:Number = Math.max(0, element.alpha + element._rule._modAlpha);
			
			for (var i:int = 0; i < objectsOnScreen.length; i++) 
			{
				var item:ScreenText = objectsOnScreen[i];
				//var distanceFromActiveElement:Number = Math.abs(10 / (element.z - item.z)) - 0.4;
				//trace(distanceFromActiveElement);
				//item.alpha = distanceFromActiveElement;
				//item.scaleX = item.scaleY = 1;
				item.filters = [];
			}
			element.alpha = 1;
			element.filters = [new GlowFilter(0xffffff, 0.4, 8, 8, 3)];
			//element.setColor(Math.random() * 0xffffff);
			
			// TODO camera move does not work correctly on FLIPPED elements!  Must make logic for these situations...
			TweenLite.to(centerClip, tweenTime, { rotationX: -element.rotationX, rotationY: -element.rotationY, rotationZ: -element.rotationZ } );	
			TweenLite.to(objectsContainer, tweenTime, { x: -newX, y: -newY, z: -newZ, alpha:1, onComplete:canvasOnDestination } );
			if (element._background != "") backgroundImage.setBackgroundImage(element._background);
			//TweenLite.to(element, 1, { scaleX:1.4, scaleY:element._scale * 1.4 } );
		}
		
		public function setActiveObject(element:ScreenText):void 
		{
			activeElement = element;
		}
		
		public function getActiveObject():ScreenText {
			return activeElement;
		}
		
		private function canvasOnDestination():void 
		{
			var zDest:Number = objectsContainer.z -80;
			TweenLite.to(objectsContainer, 5, { z: zDest } );
		}
	}

}
